package com.ruijie.acl.service;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.util.Assert;

import com.ruijie.acl.AccessGroup;
import com.ruijie.acl.AclDevice;
import com.ruijie.acl.AclDeviceAccessGroup;
import com.ruijie.emp.device.Device;
import com.ruijie.emp.system.role.internal.UserRoleUtil;
import com.ruijie.emp.system.role.type.PurviewEnum;
import com.ruijie.foundation.dao.support.Page;
import com.ruijie.foundation.exception.BusinessException;
import com.ruijie.foundation.utils.StringUtils;

/**
 * <p>
 * Title: ACL设备与ACL组关联的服务实现类
 * </p>
 * <p>
 * Description: 为ACL组和ACL设备关联关系提供逻辑处理，以及数据库的操作。
 * </p>
 * <p>
 * Copyright: Copyright (c) 2008
 * </p>
 * <p>
 * Company: Ruijie Co., Ltd.
 * </p>
 * <p>
 * Create Time: 2009-07-15
 * </p>
 * <p>
 * Update Time:
 * </p>
 * <p>
 * Updater:
 * </p>
 * <p>
 * Update Comments:
 * </p>
 * 
 * @author ASAI
 */
public class DeviceAccessGroupServiceImpl extends AclHibernateEntityExtendDao<AclDeviceAccessGroup>
		implements DeviceAccessGroupService {

	/**
	 * 根据ACL组分页查询ACL设备
	 * 
	 * @param entity
	 *            ACL组
	 * @param pageNo
	 *            页数
	 * @param pageSize
	 *            每面显示的记录数
	 * @return ACL设备
	 */
	@Override
	public Page pageQueryByAccessGroup(AccessGroup entity, int pageNo, int pageSize) {

		Assert.notNull(entity);
		Criteria criteria = createCriteria(AclDeviceAccessGroup.class);
		criteria.add(Restrictions.eq("accessGroup", entity));
		
		//---------------------------add by sinyee -------------------
		criteria.createCriteria("aclDevice","ad").add(Restrictions.sqlRestriction(UserRoleUtil.getSQLNoAnd("ad1_", "device_id")));
		
		return pagedQuery(criteria, pageNo, pageSize);

	}

	/**
	 * 根据ACL组取得所有ACL设备与ACL组关系
	 * 
	 * @param entity
	 *            ACL组
	 * @return ACL设备与ACL组关系
	 */
	@SuppressWarnings("unchecked")
	public List<AclDeviceAccessGroup> getByAccessGroup(AccessGroup entity) {
		Assert.notNull(entity);
		Criteria criteria = createCriteria(AclDeviceAccessGroup.class);
		criteria.add(Restrictions.eq("accessGroup", entity));
		return (List<AclDeviceAccessGroup>) criteria.list();
	}

	/**
	 * 根据ACL设备取得所有ACL设备与ACL组关系
	 * 
	 * @param entity
	 *            ACL设备
	 * @return ACL设备与ACL组关系
	 */
	@SuppressWarnings("unchecked")
	public List<AclDeviceAccessGroup> getByAclDevice(AclDevice entity) {
		Assert.notNull(entity);
		Criteria criteria = createCriteria(AclDeviceAccessGroup.class);
		criteria.add(Restrictions.eq("aclDevice", entity));
		return (List<AclDeviceAccessGroup>) criteria.list();
	}

	/**
	 * 根据ACL设备分页查询ACL组
	 * 
	 * @param entity
	 *            ACL设备
	 * @param pageNo
	 *            页数
	 * @param pageSize
	 *            每面显示的记录数
	 * @return ACL组
	 */
	@Override
	public Page pageQueryByAclDevice(AclDevice entity, AccessGroup group, int pageNo, int pageSize) {

		Criteria criteria = createCriteria(AclDeviceAccessGroup.class);
		if (entity != null) {
			criteria.add(Restrictions.eq("aclDevice", entity));
		}
		if (group != null) {
			Criteria groupCriteria = criteria.createCriteria("accessGroup");
			if (!StringUtils.isNullOrEmpty(group.getName())) {
				Criterion nameCriterion = Restrictions.like("name", group.getName(),
						MatchMode.ANYWHERE);
				groupCriteria.add(nameCriterion);
			}
			if (!StringUtils.isNullOrEmpty(group.getAclType())) {
				Criterion genreCriterion = Restrictions.eq("aclType", group.getAclType());
				groupCriteria.add(genreCriterion);
			}
		}
		// criteria.addOrder(org.hibernate.criterion.Order.asc("accessGroup.id"));
		return pagedQuery(criteria, pageNo, pageSize);
	}

	/**
	 * 根据ACL设备分页查询ACL组
	 * 
	 * @param entity
	 *            ACL设备
	 * @param pageNo
	 *            页数
	 * @param pageSize
	 *            每面显示的记录数
	 * @return ACL组
	 */
	public Page pageQueryByAclDeviceGroup(AclDevice entity, AccessGroup group, int pageNo,
			int pageSize) {

		Criteria criteria = createCriteria(AccessGroup.class);
		if (entity != null) {
			criteria.add(Restrictions.eq("aclDevice", entity));
		}
		if (!StringUtils.isNullOrEmpty(group.getName())) {
			criteria.add(Restrictions.like("name", group.getName(), MatchMode.ANYWHERE));
		}
		if (!StringUtils.isNullOrEmpty(group.getAclType())) {
			criteria.add(Restrictions.eq("aclType", group.getAclType()));
		}
		criteria.add(Restrictions.isNotNull("aclDevice"));
		
		//------------------------add by sinyee ------------------------
		criteria.createCriteria("aclDevice","ad").add(Restrictions.sqlRestriction(UserRoleUtil.getSQLNoAnd("ad1_", "device_id")));
		
		criteria.addOrder(Order.asc("aclDevice.id"));
		criteria.addOrder(Order.asc("id"));
		
		return pagedQuery(criteria, pageNo, pageSize);
	}

	/**
	 * 根据ACL设备和ACL组取得关系对象
	 * 
	 * @param aclDevice
	 *            ACL设备
	 * @param accessGroup
	 *            ACL组
	 * @return 关系对象
	 */
	@SuppressWarnings("unchecked")
	public AclDeviceAccessGroup getByAclDeviceAndAccessGroup(AclDevice aclDevice,
			AccessGroup accessGroup) {
		Assert.notNull(aclDevice);
		Assert.notNull(accessGroup);
		AclDeviceAccessGroup result = null;
		Criteria criteria = createCriteria(AclDeviceAccessGroup.class);
		criteria.add(Restrictions.eq("aclDevice", aclDevice));
		criteria.add(Restrictions.eq("accessGroup", accessGroup));
		List<AclDeviceAccessGroup> list = (List<AclDeviceAccessGroup>) criteria.list();
		if (list != null && list.size() > 0) {
			result = list.get(0);
		}
		return result;
	}

	/**
	 * 根据ACL设备删除ACL设备与ACL组关系
	 * 
	 * @param aclDevice
	 *            ACL设备
	 */
	public void deleteByAclDevice(AclDevice aclDevice) {
		String hql = "delete from AclDeviceAccessGroup where aclDevice=?";
		this.createQuery(hql, aclDevice).executeUpdate();
	}

	/**
	 * 根据ACL组删除ACL设备与ACL组关系
	 * 
	 * @param accessGroup
	 *            ACL组
	 */
	public void deleteByAccessGroups(String groupIds, AclDevice aclDevice) {
		Assert.notNull(groupIds);
		String hql = "delete from AclDeviceAccessGroup where aclDevice=? and  accessGroup.id in ("
				+ groupIds + ")";
		this.createQuery(hql, aclDevice).executeUpdate();
	}

	/**
	 * 根据ACL组判断是否存在ACL设备与ACL组关系
	 * 
	 * @param entity
	 *            ACL组
	 * @return 是否存在ACL设备与ACL组关系
	 */
	public boolean existByAccessGroup(AccessGroup entity) {
		Assert.notNull(entity);
		Criteria criteria = createCriteria(AclDeviceAccessGroup.class);
		criteria.add(Restrictions.eq("accessGroup", entity));
		int count = (Integer) criteria.setProjection(Projections.rowCount()).uniqueResult();
		return count > 0;
	}

	/**
	 * 根据ACL组判断是否存在修改标志位为已修改的ACL设备与ACL组关系
	 * 
	 * @param entity
	 *            ACL组
	 * @return 是否存在ACL设备与ACL组关系
	 */
	public boolean existByAccessGroupAndChanged(AccessGroup entity) {
		Assert.notNull(entity);
		Criteria criteria = createCriteria(AclDeviceAccessGroup.class);
		criteria.add(Restrictions.eq("accessGroup", entity));
		criteria.add(Restrictions.eq("isChanged", true));
		int count = (Integer) criteria.setProjection(Projections.rowCount()).uniqueResult();
		return count > 0;
	}

	/**
	 * 取得与组关联并且不一致的ACL设备
	 * 
	 * @param entity
	 *            ACL组
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<AclDeviceAccessGroup> findByAccessGroupAndChanged(AccessGroup entity) {
		Assert.notNull(entity);
		Criteria criteria = createCriteria(AclDeviceAccessGroup.class);
		criteria.add(Restrictions.eq("accessGroup", entity));
		criteria.add(Restrictions.eq("isChanged", true));
		return criteria.list();
	}

	/**
	 * 根据ACL组更新关系的修改标志位
	 * 
	 * @param entity
	 *            ACL组
	 */
	public void updateChangedByAccessGroup(AccessGroup entity) {
		String hql = "update AclDeviceAccessGroup set isChanged = ? where accessGroup = ?";
		this.createQuery(hql, entity.getIsChanged(), entity).executeUpdate();
	}
	
	/**
	 * 根据ACL组更新关系的修改标志位
	 * 
	 * @param entity
	 *            ACL组
	 */
	public void updateChangedByAccessGroup(AccessGroup entity,boolean isChanged,AclDevice aclDevice) {
		List<Object> paramList = new ArrayList<Object>();
		String hql = "update AclDeviceAccessGroup set isChanged = ? where accessGroup = ? and aclDevice=?";
		this.createQuery(hql, isChanged, entity,aclDevice).executeUpdate();
	}

	/**
	 * 添加设备与组的关系
	 * 
	 * @param accessGroupList
	 *            组列表
	 * @param device
	 *            设备
	 * @throws Exception
	 */
	public void addAccessGroupDevices(List<AccessGroup> accessGroupList, Device device)
			throws Exception {
		Assert.notNull(device);
		// 取得Acl Device
		AclDevice aclDevice = this.findUniqueBy(AclDevice.class, "device", device);
		// 如果不是Acl Device
		if (aclDevice == null) {
			// 该设备不是ACL设备，无法与ACL组创建关联。
			throw new BusinessException("acl_device_access_group_error_no_acldevice");
		}
		/*
		 * if (accessGroupList != null && accessGroupList.size() > 0){ String
		 * groupIds = ""; // 先删除关系 for(AccessGroup accessGroup:accessGroupList){
		 * groupIds += "," + accessGroup.getId(); }
		 * this.deleteByAccessGroups(groupIds.substring(1),aclDevice); // 创建关系
		 * for(AccessGroup accessGroup:accessGroupList){ AclDeviceAccessGroup
		 * aclDeviceAccessGroup = new AclDeviceAccessGroup();
		 * aclDeviceAccessGroup.setAccessGroup(accessGroup);
		 * aclDeviceAccessGroup.setAclDevice(aclDevice);
		 * this.save(aclDeviceAccessGroup); } }
		 */
		if (accessGroupList != null && accessGroupList.size() > 0) {
			for (AccessGroup accessGroup : accessGroupList) {
				if (accessGroup != null && accessGroup.getAclDevice() == null) {
					// 为了防止组被删除
					try {
						this.refresh(accessGroup);
					} catch (Exception ex) {
						return;
					}
					AclDeviceAccessGroup entity = this.getByAclDeviceAndAccessGroup(aclDevice,
							accessGroup);
					if (entity == null) {
						// 不存在此ACL组与ACL设备关联时,新建一个
						entity = new AclDeviceAccessGroup();
						entity.setAclDevice(aclDevice);
						entity.setAccessGroup(accessGroup);
						this.save(entity);
					} else {
						// 若存在,且其修改标志为不一致时,修改其修改标志位
						if (entity.getIsChanged()) {
							entity.setIsChanged(false);
							this.update(entity);
						}
					}

				}
			}
		}
	}

	/**
	 * 根据ACL设备取得ACL组
	 * 
	 * @param entity
	 *            ACL设备
	 * @return ACL组列表
	 */
	public List<AccessGroup> getAccessGroupByAclDevice(AclDevice entity) {
		List<AccessGroup> list = new ArrayList<AccessGroup>();
		List<AclDeviceAccessGroup> aclDeviceAccessGroupList = getByAclDevice(entity);
		if (aclDeviceAccessGroupList != null && aclDeviceAccessGroupList.size() > 0) {
			for (AclDeviceAccessGroup aclDeviceAccessGroup : aclDeviceAccessGroupList) {
				list.add(aclDeviceAccessGroup.getAccessGroup());
			}
		}
		return list;
	}
}
